#!/bin/bash

echo "docker GPT-SoVITS make"

# 拉取镜像
docker pull breakstring/gpt-sovits:latest

# 查看内存
free -h

if [ ! -e /opt/soVits/tmp ]; then mkdir -p /opt/soVits/tmp; fi
if [ ! -e /opt/soVits/logs ]; then mkdir -p /opt/soVits/logs; fi
if [ ! -e /opt/soVits/input ]; then mkdir -p /opt/soVits/input; fi
if [ ! -e /opt/soVits/output ]; then mkdir -p /opt/soVits/output; fi
if [ ! -e /opt/soVits/GPT_weights ]; then mkdir -p /opt/soVits/GPT_weights; fi
if [ ! -e /opt/soVits/SoVITS_weights ]; then mkdir -p /opt/soVits/SoVITS_weights; fi

docker run -itd \
    --gpus=all \
    --env=is_half=False \
    --volume=/opt/soVits/tmp:/workspace/TEMP \
    --volume=/opt/soVits/logs:/workspace/logs \
    --volume=/opt/soVits/input:/workspace/input \
    --volume=/opt/soVits/output:/workspace/output \
    --volume=/opt/soVits/GPT_weights:/workspace/GPT_weights \
    --volume=/opt/soVits/SoVITS_weights:/workspace/SoVITS_weights \
    --workdir=/workspace \
    --name soVits \
    --network allinpay \
    -p 9880:9880 \
    -p 9871:9871 \
    -p 9872:9872 \
    -p 9873:9873 \
    -p 9874:9874 \
    --shm-size="32G" \
    --restart=always \
    breakstring/gpt-sovits:latest

docker update --restart=always soVits

firewall-cmd --add-port=9880/tcp --permanent
firewall-cmd --add-port=9871/tcp --permanent
firewall-cmd --add-port=9872/tcp --permanent
firewall-cmd --add-port=9873/tcp --permanent
firewall-cmd --add-port=9874/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-all

# 编辑文件
# cp inference_webui.py /workspace/GPT_SoVITS

# ===================================
# 操作流程文档
# ===================================

# 下载预训练模型GPT-SoVITS Models和BGM分离UVR5 Weights
# https://www.icloud.com.cn/iclouddrive/056y_Xog_HXpALuVUjscIwTtg#GPT-SoVITS_Models
# 下载语音识别中，英，日

# TTS输出格式
# vocal_path|speaker_name|language|text
# D:\GPT-SoVITS\xxx/xxx.wav|xxx|en|I like playing Genshin.

# 6：分享模型
# 分享需要的模型都在SoVITS_weights和GPT_weights这两个文件夹，选择合适轮数的模型，
# 记得带上参考音频一起打包成压缩文件，就可以分享了。别人只要将GPT模型（ckpt后缀）放入GPT_weights文件夹，
# SoVITS模型（pth后缀）放入SoVITS_weights文件夹就可以推理了

# 7：使用别人分享的模型
# 将GPT模型（ckpt后缀）放入GPT_weights文件夹，SoVITS模型（pth后缀）放入SoVITS_weights文件夹，
# 刷新下模型就能选择模型推理了。


# 分离BGM, 提取人声
1, 勾选 Open UVR5-WebUI, 打开http://192.168.31.212:9873/, 
    上传声音样本：
    先用HP2模型处理一遍（提取人声），处理完的音频（vocal）的是人声，(instrument)是伴奏，记得把instrument删掉。
    然后将输出的干声文件再用onnx_dereverb, *_main_vocal.wav保留，*_others.wav删掉。
    最后用DeEcho-Aggressive（去混响），
    输出格式选wav。
    输出的文件默认在GPT-SoVITS-beta\GPT-SoVITS-beta\output\uvr5_opt这个文件夹下，
    
    结束后记得到WebUI关闭UVR5节省显存。

# 切割音频
1, 在切割音频前建议把所有音频拖进音频软件（如au、剪映）调整音量，最大音量调整至-9dB到-6dB，过高的删除
    min_length根据显存大小调整，显存越小调越小。
    min_interval根据音频的平均间隔调整，如果音频太密集可以适当调低。
    max_sil_kept会影响句子的连贯性，不同音频不同调整，不会调的话保持默认。
    其他参数不建议调整

# 音频降噪
1,在0221版本之后才有这个功能而且不太好用，对音质的破坏很大，谨慎使用。

# 打标和校对标注
1, 把刚才的切分文件夹输入，然后选择达摩ASR或者fast whisper。
    达摩ASR只能用于识别中文，效果也最好。
    fast whisper可以标注99种语言，是目前最好的英语和日语识别，
    模型尺寸选large V3，语种选auto自动就好了。
    然后点开启离线批量ASR就好了，
    默认输出是output/slicer_opt这个路径，
    ASR需要一些时间，看着控制台有没有报错就好了
2, 输入标注文件的文件路径，注意是文件路径！不是文件夹路径！
    示例：/content/GPT-SoVITS/output/asr_opt/slicer_opt.list 
    注意后面的文件名必须要输进去！打不开就再三检查路径是否正确！
    必须要有.list的后缀！！！
    然后开启打标webui
    http://192.168.31.212:9871/

# 训练
1, 先设置实验名也就是模型名，不要有中文
    第一个输入的是标注文件路径，注意是文件路径！不是文件夹路径！
    示例：/content/GPT-SoVITS/output/asr_opt/slicer_opt.list 
    注意后面的文件名必须要输进去！打不开就再三检查路径是否正确！必须要有.list的后缀！！！
    第二个输入的是切分音频文件夹路径 示例：/content/GPT-SoVITS/output/slicer_opt。
    注意复制的路径都不能有引号！！！千万不能有引号！
    然后点一键三连。（1Aabc-One-click formatting）

# 微调训练
1,  首先设置batch_size，建议batch_size设置为显存的一半以下，高了会爆显存。
    colab免费的卡是Tasla T4是16g显存，所以设置8差不多。
    bs并不是越高越快！batch_size也需要根据数据集大小调整，也并不是严格按照显存数一半来设置，
    比如6g显存需要设置为1。如果爆显存就调低。
    当显卡3D占用100%的时候就是bs太高了，使用到了共享显存，速度会慢好几倍。
    GPT模型训练的时候可以把bs再调低点。
2,  接着设置轮数，SoVITS模型轮数可以设置的高一点，反正训练的很快。
    GPT模型轮数千万不能高于20（一般情况下）建议设置10。
    然后先点开启SoVITS训练，训练完后再点开启GPT训练，
    不可以一起训练！（除非你有两张卡）
    如果中途中断了，直接再点开始训练就好了，会从最近的保存点开始训练。

# 推理
1, 先点一下刷新模型，下拉选择模型推理，e代表轮数，s代表步数。
    不是轮数越高越好。选择好模型点开启TTS推理，
    在控制台点最下面的链接: http://192.168.31.212:9872/
2, 上传一段参考音频，建议是数据集中的音频。最好5秒。
    参考音频很重要！会学习语速和语气，请认真选择。
    参考音频的文本是参考音频说什么就填什么，必须要填。语种也要对应
3, 接着就是输入要合成的文本了，注意语种要对应。
    目前可以中英混合，日英混合和中日英混合。
    切分建议无脑选50字一切，低于50字的不会切。
    如果50字一切报错的话就是显存太小了可以按句号切。
    如果不切，显存越大能合成的越多，实测4090大约1000字，但已经胡言乱语了，
    所以哪怕你是4090也建议切分生成。
    合成的过长很容易胡言乱语。如果出现吞字，重复，参考音频混入的情况，这是正常现象。
    不是模型炼差了，不用为模型担心。
    改善的方法有使用较低轮数的GPT模型、合成文本再短点、换参考音频。
    官方也在努力修复这个问题。


